package com.zf.bm.common.core.sys.web;

import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zf.bm.common.constant.Constant;
import com.zf.bm.common.core.config.ConfigUtils;
import com.zf.bm.common.core.log.annotation.SysLog;
import com.zf.bm.common.core.shiro.utils.ShiroUtils;
import com.zf.bm.common.core.sys.entity.Role;
import com.zf.bm.common.core.sys.entity.User;
import com.zf.bm.common.core.sys.service.SystemService;
import com.zf.bm.common.core.sys.service.UserService;
import com.zf.bm.common.core.sys.service.WeakPasswordService;
import com.zf.bm.common.dto.ObjectConvert;
import com.zf.bm.common.core.sys.dto.UserDTO;
import com.zf.bm.common.utils.excel.ExcelUtil;
import com.zf.bm.common.web.BaseController;
import com.zf.bm.modules.system.service.MonitorAuditLogService;
import com.zf.bm.modules.system.utils.SystemUtils;
import com.zf.bm.vo.ModifyPwdVo;
import com.zf.bm.vo.UserSearchVo;
import com.zf.bm.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.zf.bm.common.constant.Constant.CenterAuditType.ENUM_USER_OPT;

@Slf4j
@RestController
@RequestMapping(value = "${adminPath}/sys/user", method = {RequestMethod.GET, RequestMethod.POST})
public class UserController extends BaseController {

    @Autowired
    private SystemService systemService;
    @Autowired
    private MonitorAuditLogService logService;
    @Autowired
    private WeakPasswordService weakPasswordService;
    @Resource
    private UserService userService;

    @SysLog("用户查询")
    @RequestMapping(value = "list")
    public Result list(@RequestBody UserSearchVo vo) {
        User user = new User();
        Page p = new Page<User>();
        p.setCurrent(vo.getPage());
        p.setSize(vo.getSize());
        user.setLoginName(vo.getUsername().replaceAll("%","/%").replaceAll("_","/_"));
        user.setLoginFlag(vo.getEnabled());
        user.setId(UserUtils.getUser().getId());
        IPage<User> page = systemService.findUser(p, user);
        List<User> users = page.getRecords();
        Map<String, Object> result = Maps.newHashMap();
        result.put("content", userToDtoList(users));
        result.put("total", page.getTotal());
        return new Result(result);
    }

    @SysLog("用户数据")
    @RequestMapping(value = {"listData"})
    public Result listData(User user) {
        IPage<User> page = systemService.findUser(new Page(), user);
        return new Result(page);
    }


    @SysLog("保存用户")
    @RequiresPermissions("sys:user:edit")
    @RequestMapping(value = "save")
    public Result save(@RequestBody UserVo vo) {
        ObjectConvert<User> convert = new ObjectConvert();
        User user = convert.toObj(vo, new User());
        user.setRoleIdList(vo.getRoles());
        user.setUsbKey(vo.getUsbKey());
        if (Objects.isNull(user.getId())) {
            user.setPassword(ShiroUtils.entryptPassword(defPwd));
            //Base64加密
            user.setKeyPassword(Base64Util.encryption(defPwd));
        }
        user.setName(user.getLoginName());
        //页面 传参 修改密码栏位不为空
        if(ValidatorUtil.isNotEmptyObj(vo.getOriginalPassword()) && ValidatorUtil.isNotEmptyObj(vo.getChangedPassword())){
            try {
                //解密
                String updateNewPassword = EncryptUtils.decrypt(vo.getChangedPassword());
                if (checkWeakPassword(updateNewPassword)){
                    return new Result(ResultStatus.FAIL.getCode(),"新密码为弱密码请重新配置");
                }
                user.setPassword(ShiroUtils.entryptPassword(updateNewPassword));
                //sm4加密算法
                user.setKeyPassword(Base64Util.encryption(updateNewPassword));
            } catch (Exception e) {
                log.error("exception:",e);
            }

        }
        if (!beanValidator(user)) {
            return new Result(ResultStatus.DATA_CHECK_FAIL);
        }
        if (!checkLoginName(user.getId(), user.getLoginName())) {
            return new Result(ResultStatus.USER_ALREADY_EXIST.getCode(),
                    "保存用户'" + user.getLoginName() + "'失败，登录名已存在");
        }
        // 角色数据有效性验证，过滤不在授权内的角色
        List<Role> roleList = Lists.newArrayList();
        List<Long> roleIdList = user.getRoleIdList();
        for (Role r : systemService.findAllRole()) {
            if (roleIdList.contains(r.getId())) {
                roleList.add(r);
            }
        }
        user.setRoleList(roleList);
        if ("0".equals(user.getLoginFlag())) {
            user.setFrozenDate(new Date(System.currentTimeMillis() + 30 * 60 * 1000));
        }
        // 保存用户信息
        systemService.saveUser(user);
        // 清除当前用户缓存
        if (user.getLoginName().equals(UserUtils.getUser().getLoginName())) {
            UserUtils.clearCache();
        }
        return new Result("保存用户" + user.getLoginName() + "成功");
    }

    @SysLog("用户删除")
    @RequiresPermissions("sys:user:edit")
    @RequestMapping(value = "delete")
    public Result delete(@RequestBody UserVo vo) {
        Long id = vo.getId();
        User user = new User(id).selectById();
        if (UserUtils.getUser().getId().equals(user.getId())) {
            return new Result(ResultStatus.FAIL.getCode(),
                    "删除用户失败, 不允许删除当前用户");
        } else if (User.isAdmin(user.getId())) {
            return new Result(ResultStatus.FAIL.getCode(),
                    "删除用户失败, 不允许删除超级管理员用户");
        } else if(user.getId() == 3 || user.getId() ==4){
            return new Result(ResultStatus.FAIL.getCode(),
                    "删除用户失败, 不允许删除默认三元用户");
        }else {
            systemService.deleteUser(user);
        }
        SystemUtils.saveSystemLog("用户", "删除", 3, "用户" + user.getLoginName() + "删除成功");
        // 保存用户日志
        String operateDesc = "删除用户"+user.getLoginName();
        logService.saveMonitorAuditLog("删除用户", operateDesc, ENUM_USER_OPT.getMsg());
        return new Result("删除用户成功" + user.getLoginName() + "成功");
    }

    /**
     * 导出用户数据
     *
     * @param vo
     * @param response
     * @return
     */
    @SysLog("导出用户数据")
    @RequiresPermissions("sys:user:view")
    @PostMapping(value = "export")
    public Result exportFile(@RequestBody UserSearchVo vo, HttpServletResponse response) {

        User user = new User();
        Page p = new Page<User>();
        p.setCurrent(vo.getPage() + 1L);
        p.setSize(vo.getSize());
        user.setLoginName(vo.getUsername());
        user.setLoginFlag(vo.getEnabled());
        try {
            user.setId(UserUtils.getUser().getId());
            String fileName = "用户数据" + DateTimeUtils.getDate("yyyyMMddHHmmss");
            IPage<User> page = systemService.findUser(p, user);
            List<User> users = page.getRecords();
            if (CollectionUtils.isNotEmpty(users)) {
                for (int j = 0; j <users.size();j++) {
                    String logFlag = users.get(j).getLoginFlag();
                    logFlag = logFlag.equals("1") ? "正常" : "锁定";
                    users.get(j).setLoginFlag(logFlag);
                    List<UserDTO> userDTOS = userToDtoList(users);
                    users.get(j).setRoleName(userDTOS.get(j).getRoles().get(0).get("name").toString());//获取角色 回传
                    }
                }
            ExcelUtil.writeExcel(response, userToDtoList(page.getRecords()), fileName, "", ExcelTypeEnum.XLSX, UserDTO.class);
            return null;
        } catch (Exception e) {
            return new Result(ResultStatus.FAIL.getCode(),
                    "导出用户失败！失败信息" + e.getMessage());
        }
    }


    private List<UserDTO> userToDtoList(List<User> list) {
        List<UserDTO> listDto = Lists.newArrayList();
        if (!Collections3.isEmpty(list)) {
            for (int i = 0; i < list.size(); i++) {
                User u = list.get(i);
                List<Role> roleList = UserUtils.get(u.getId()).getRoleList();
                u.setRoleList(roleList);
                ObjectConvert<UserDTO> objectToDto = new ObjectConvert();
                listDto.add(objectToDto.toDto(u, new UserDTO()));

            }
        }
        return listDto;
    }

    /**
     * 验证登录名是否有效
     *
     * @param loginName
     * @return
     */
    public Boolean checkLoginName(Long id, String loginName) {
        User user = systemService.getUserByLoginName(loginName);
        if (user == null) {
            return Boolean.TRUE;
        } else if (id == null || (user.getId().longValue() != id.longValue())) {
            return Boolean.FALSE;
        } else if (id != null && user.getId().longValue() != id.longValue()) {
            return Boolean.FALSE;

        }
        return Boolean.TRUE;
    }

    /**
     * 当前用户信息
     *
     * @return
     */
    @SysLog("当前用户信息")
    @RequestMapping(value = "info")
    public Result info() {
        User userObject = UserUtils.getUser();
        if (ValidatorUtil.isEmptyObj(userObject)) {
            return new Result(ResultStatus.FAIL);
        }

        UserDTO userDTO = new UserDTO();
        User user = UserUtils.getByLoginName(userObject.getLoginName());
        ObjectConvert<UserDTO> objectToDto = new ObjectConvert();
        userDTO = objectToDto.toDto(user, userDTO);
        userDTO.setIsGuide(userService.isGuide(userDTO.getUsername()));
        Map<String, UserDTO> result = Maps.newHashMap();
        result.put("content", userDTO);
        return new Result(result);
    }


    /**
     * 修改个人用户密码
     *
     * @return
     */
    @SysLog("修改个人用户密码")
    @RequestMapping(value = "modifyPwd")
    public Result modifyPwd(@RequestBody ModifyPwdVo vo) {
        User user = UserUtils.getUser();
        try {
            String oldPassword = EncryptUtils.decrypt(vo.getOldPassword());
            String newPassword = EncryptUtils.decrypt(vo.getNewPassword());
            String userName = vo.getUserName();
            if (Objects.nonNull(vo.getId())) {
                //密码重置
                user = systemService.getUser(vo.getId());
                systemService.updatePasswordById(user.getId(), user.getLoginName(),
                        ConfigUtils.getConfig("sys.def.pwd"), Constant.MODIFY_PWD_RESET, user.getName());
                return new Result("修改密码成功");
            }

            if (StringUtil.isNotBlank(oldPassword) && StringUtil.isNotBlank(newPassword)) {
                if (checkWeakPassword(newPassword)){
                    return new Result(ResultStatus.FAIL.getCode(),"新密码为弱密码请重新配置");
                }
                if (!user.getLoginName().equals(vo.getUserName()) && !checkLoginName(user.getId(),userName)){
                    return new Result(ResultStatus.FAIL.getCode(),"用户名已存在");
                }
                boolean flag = ShiroUtils.validatePassword(oldPassword, user.getPassword());
                if (flag) {
                    systemService.updatePasswordById(user.getId(), user.getLoginName(), newPassword, 1, userName);
                    return new Result("修改密码成功");
                } else {
                    return new Result(ResultStatus.USER_PASS_EDIT_FAIL);
                }
            }

        } catch (Exception e) {
            log.error("exception:",e);
        }
        return new Result(user);
    }


    @SysLog("修改用户个人信息")
    @RequestMapping(value = "saveSelf")
    public Result saveSelf(@RequestBody UserVo vo) {
        ObjectConvert<User> convert = new ObjectConvert();
        User user = convert.toObj(vo, new User());
        user.setRoleIdList(vo.getRoles());
        if (Objects.isNull(user.getId())) {
            user.setPassword(ShiroUtils.entryptPassword(defPwd));
        }
        user.setName(user.getLoginName());
        // 如果新密码为空，则不更换密码
        if (StringUtil.isNotBlank(user.getNewPassword())) {
            user.setPassword(user.getNewPassword());
        }
        if (!beanValidator(user)) {
            return new Result(ResultStatus.DATA_CHECK_FAIL);
        }
        if (!checkLoginName(user.getId(), user.getLoginName())) {
            return new Result(ResultStatus.USER_ALREADY_EXIST.getCode(),
                    "保存用户'" + user.getLoginName() + "'失败，登录名已存在");
        }
        // 角色数据有效性验证，过滤不在授权内的角色
        List<Role> roleList = Lists.newArrayList();
        List<Long> roleIdList = user.getRoleIdList();
        for (Role r : systemService.findAllRole()) {
            if (roleIdList.contains(r.getId())) {
                roleList.add(r);
            }
        }
        user.setRoleList(roleList);
        if ("0".equals(user.getLoginFlag())) {
            user.setFrozenDate(new Date(System.currentTimeMillis() + 30 * 60 * 1000));
        }
        // 保存用户信息
        systemService.saveUser(user);
        // 清除当前用户缓存
        if (user.getLoginName().equals(UserUtils.getUser().getLoginName())) {
            UserUtils.clearCache();
        }
        return new Result("保存用户" + user.getLoginName() + "成功");
    }

    public Boolean checkWeakPassword(String newPassword){
        List<String> weakPasswordList = weakPasswordService.getWeakPassword();
        for (String s : weakPasswordList){
            if (newPassword.equals(s)){
                return true;
            }
        }

        return false;
    }

}
